/*
 * File Name：WheelView.java
 * Copyright：Copyright 2008-2012 CiWong.Inc. All Rights Reserved.
 * Description： WheelView.java
 * Modify By：PLA-BBTAN
 * Modify Date：2012-11-17
 * Modify Type：Add
 */
package com.ciwong.epaper.widget.wheel;

import java.util.LinkedList;
import java.util.List;


import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.FloatMath;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Interpolator;
import android.widget.Scroller;

import com.ciwong.epaper.R;
import com.ciwong.epaper.widget.wheel.i.OnWheelChangedListener;
import com.ciwong.epaper.widget.wheel.i.OnWheelViewChangedListener;
import com.ciwong.epaper.widget.wheel.i.OnWheelViewScrollListener;
import com.ciwong.epaper.widget.wheel.i.WheelAdapter;

/**
 * 滚轮视图
 *
 * @author PLA-BBTAN
 * @version ciwong v.1.0 2012-11-17
 * @since ciwong v.1.0
 */
public class WheelChooserView extends View {
    /**
     * 省
     */
    private static final String PROVINCE = "省";

    /**
     * 滚动时间
     */
    private static final int SCROLLING_DURATION = 400;

    /**
     * 最小滚动增量
     */
    private static final int MIN_DELTA_FOR_SCROLLING = 1;

    /**
     * 当前值和标签的文字颜色
     */
    private static final int VALUE_TEXT_COLOR = Color.parseColor("#505050");

    /**
     * 选项的颜色
     */
    private static final int ITEMS_TEXT_COLOR = Color.parseColor("#929292");

    // /** 顶部和底部的阴影颜色 */
    // private static final int[] SHADOWS_COLORS = new int[]{0xFF111111,
    // 0x00AAAAAA, 0x00AAAAAA};

    /**
     * 其他选项的高度（被添加到标准的文本项高度）
     */
    private static final int ADDITIONAL_ITEM_HEIGHT = 55;

    /**
     * 其他选项宽度布局
     */
    private static final int ADDITIONAL_ITEMS_SPACE = 55;

    /**
     * 标签偏移量
     */
    private static final int LABEL_OFFSET = 8;

    /**
     * 左和右填充值
     */
    private static final int PADDING = 10;

    /**
     * 默认能看到多少项
     */
    private static final int DEF_VISIBLE_ITEMS = 5;

    // Messages
    private final int messageScroll = 0;

    private final int messageJustify = 1;

    private final int mmColor = 0x7FFFFFFF;

    private final int mShadowColor = 0xFFC0C0C0;

    private final int two = 2;

    private final int five = 5;

    private final float mRadio = 0.1f;

    private final float mDy = 0.1f;

    /**
     * 文字的大小
     */
    private int textSize;

    /**
     * 偏移量（隐藏，顶部和底部的项目）
     */
    private int itemOffset = getTextSize() / five;

    /**
     * 滚轮适配器
     */
    private WheelAdapter mAdapter = null;

    private int currentItem = 0;

    /**
     * 选项的宽度
     */
    private int itemsWidth = 0;

    /**
     * 标签的宽度
     */
    private int labelWidth = 0;

    /**
     * 可见项计数
     */
    private int visibleItems = DEF_VISIBLE_ITEMS;

    /**
     * 选项的高度
     */
    private int mItemHeight = 0;

    /**
     * 文字画笔
     */
    private TextPaint itemsPaint;

    private TextPaint valuePaint;

    // private TextPaint bgPaint;

    /**
     * 布局
     */
    private StaticLayout itemsLayout;

    private StaticLayout labelLayout;

    private StaticLayout valueLayout;

    /**
     * 标签和背景
     */
    private String label;

    /**
     * 中间选择显示项
     */
    private Drawable centerDrawable;

    /**
     * 是否滚动
     */
    private boolean isScrollingPerformed;

    private int scrollingOffset;

    /**
     * 滚动动画
     */
    private GestureDetector gestureDetector;

    private Scroller scroller;

    private int lastScrollY;

    /**
     * 循环
     */
    private boolean mIsCyclic = false;

    /**
     * 监听器
     */
    private List<OnWheelViewChangedListener> changingListeners = new LinkedList<OnWheelViewChangedListener>();

    private List<OnWheelViewScrollListener> scrollingListeners = new LinkedList<OnWheelViewScrollListener>();

    private int maxTextLength;

    private boolean isPad = false;

    // gesture listener
    private SimpleOnGestureListener gestureListener = new SimpleOnGestureListener() {
        public boolean onDown(MotionEvent e) {
            if (isScrollingPerformed) {
                scroller.forceFinished(true);
                clearMessages();
                return true;
            }
            return false;
        }

        public boolean onScroll(MotionEvent e1, MotionEvent e2,
                                float distanceX, float distanceY) {
            startScrolling();
            doScroll((int) -distanceY);
            return true;
        }

        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                               float velocityY) {
            lastScrollY = currentItem * getItemHeight() + scrollingOffset;
            int maxY = mIsCyclic ? mmColor : mAdapter.getItemsCount()
                    * getItemHeight();
            int minY = mIsCyclic ? -maxY : 0;
            scroller.fling(0, lastScrollY, 0, (int) -velocityY / two, 0, 0,
                    minY, maxY);
            setNextMessage(messageScroll);
            return true;
        }
    };

    // 动画处理
    private Handler animationHandler = new Handler() {
        public void handleMessage(Message msg) {
            scroller.computeScrollOffset();
            int currY = scroller.getCurrY();
            int delta = lastScrollY - currY;
            lastScrollY = currY;
            if (delta != 0) {
                doScroll(delta);
            }
            if (Math.abs(currY - scroller.getFinalY()) < MIN_DELTA_FOR_SCROLLING) {
                currY = scroller.getFinalY();
                scroller.forceFinished(true);
            }
            if (!scroller.isFinished()) {
                animationHandler.sendEmptyMessage(msg.what);
            } else if (msg.what == messageScroll) {
                justify();
            } else {
                finishScrolling();
            }
        }
    };

    /**
     * 滚轮视图
     *
     * @param context  上下文
     * @param attrs    属性
     * @param defStyle 样式
     */
    public WheelChooserView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initData(context);
    }

    /**
     * 滚轮视图
     *
     * @param context 上下文
     * @param attrs   属性
     */
    public WheelChooserView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initData(context);
    }

    /**
     * 滚轮视图
     *
     * @param context 上下文
     */
    public WheelChooserView(Context context) {
        super(context);
        initData(context);
    }

    public int getTextSize() {
        return textSize;
    }

    public void setTextSize(int textSize) {
        this.textSize = textSize;
    }

    /**
     * 初始化数据
     *
     * @param context 上下文
     */
    private void initData(Context context) {
        gestureDetector = new GestureDetector(context, gestureListener);
        gestureDetector.setIsLongpressEnabled(false);

        scroller = new Scroller(context);

        isPad = isPad(context);
    }

    /**
     * 获取滚轮的适配器
     *
     * @return 返回滚轮适配器
     */
    public WheelAdapter getAdapter() {
        return mAdapter;
    }

    /**
     * 设置滚轮适配器
     *
     * @param adapter 新的滚轮适配器
     */
    public void setAdapter(WheelAdapter adapter) {
        this.mAdapter = adapter;
        invalidateLayouts();
        invalidate();
    }

    /**
     * 设置指定的滚动分类
     *
     * @param interpolator 分类
     */
    public void setInterpolator(Interpolator interpolator) {
        scroller.forceFinished(true);
        scroller = new Scroller(getContext(), interpolator);
    }

    /**
     * 获取可见项数量
     *
     * @return 可见项数量
     */
    public int getVisibleItems() {
        return visibleItems;
    }

    /**
     * 设置可见项数量
     *
     * @param count 新的可见项数量
     */
    public void setVisibleItems(int count) {
        visibleItems = count;
        invalidate();
    }

    /**
     * 获取标签
     *
     * @return 标签
     */
    public String getLabel() {
        return label;
    }

    /**
     * 设置标签
     *
     * @param newLabel 传人新标签
     */
    public void setLabel(String newLabel) {
        if (label == null || !label.equals(newLabel)) {
            label = newLabel;
            labelLayout = null;
            invalidate();
        }
    }

    /**
     * 添加滚轮监听器
     *
     * @param listener 监听器
     */
    public void addChangingListener(OnWheelViewChangedListener listener) {
        changingListeners.add(listener);
    }

    /**
     * 删除滚轮监听器
     *
     * @param listener 监听器
     */
    public void removeChangingListener(OnWheelChangedListener listener) {
        changingListeners.remove(listener);
    }

    /**
     * 刷新监听器
     *
     * @param oldValue 当前值
     * @param newValue 滚动后的值
     */
    protected void notifyChangingListeners(int oldValue, int newValue) {
        for (OnWheelViewChangedListener listener : changingListeners) {
            listener.onChanged(this, oldValue, newValue);
        }
    }

    /**
     * 添加滚轮滚动监听器
     *
     * @param listener 监听器
     */
    public void addScrollingListener(OnWheelViewScrollListener listener) {
        scrollingListeners.add(listener);
    }

    /**
     * 删除滚轮滚动监听器
     *
     * @param listener 监听器
     */
    public void removeScrollingListener(OnWheelViewScrollListener listener) {
        scrollingListeners.remove(listener);
    }

    /**
     * 通知滚动器开始滚动
     */
    protected void notifyScrollingListenersAboutStart() {
        for (OnWheelViewScrollListener listener : scrollingListeners) {
            listener.onScrollingStarted(this);
        }
    }

    /**
     * 通知滚动器解释滚动
     */
    protected void notifyScrollingListenersAboutEnd() {
        for (OnWheelViewScrollListener listener : scrollingListeners) {
            listener.onScrollingFinished(this);
        }
    }

    /**
     * 获取当前的值
     *
     * @return 当前选中项的索引
     */
    public int getCurrentItem() {
        return currentItem;
    }

    /**
     * 设置当前项目。不执行任何操作时指数是错误的
     *
     * @param index    索引
     * @param animated 动画标志
     */
    public void setCurrentItem(int index, boolean animated) {
        if (mAdapter == null || mAdapter.getItemsCount() == 0) {
            return; // throw?
        }
        if (index < 0 || index >= mAdapter.getItemsCount()) {
            if (mIsCyclic) {
                while (index < 0) {
                    index += mAdapter.getItemsCount();
                }
                index %= mAdapter.getItemsCount();
            } else {
                return; // throw?
            }
        }
        if (index != currentItem) {
            if (animated) {
                scroll(index - currentItem, SCROLLING_DURATION);
            } else {
                invalidateLayouts();

                int old = currentItem;
                currentItem = index;

                notifyChangingListeners(old, currentItem);

                invalidate();
            }
        }
    }

    /**
     * 设置当前项目的W / O型动画。不执行任何操作时指数是错误的。
     *
     * @param index 索引
     */
    public void setCurrentItem(int index) {
        setCurrentItem(index, false);
    }

    /**
     * 测试，如果轮循环。这意味着之前的第一项有示出的最后一个
     *
     * @return 为true时就轮回循环
     */
    public boolean isCyclic() {
        return mIsCyclic;
    }

    /**
     * 设置轮循环标志
     *
     * @param isCyclic 标志设置
     */
    public void setCyclic(boolean isCyclic) {
        this.mIsCyclic = isCyclic;

        invalidate();
        invalidateLayouts();
    }

    /**
     * 初始化布局
     */
    private void invalidateLayouts() {
        itemsLayout = null;
        valueLayout = null;
        scrollingOffset = 0;
    }

    /**
     * 初始化资源
     */
    private void initResourcesIfNecessary() {
        if (itemsPaint == null) {
            itemsPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
            // itemsPaint.density = getResources().getDisplayMetrics().density;
            itemsPaint.setTextSize(textSize);
            itemsPaint.setColor(Color.WHITE);
        }

        if (valuePaint == null) {
            valuePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
            // valuePaint.density = getResources().getDisplayMetrics().density;
            valuePaint.setTextSize(textSize);
            // valuePaint.setShadowLayer(mRadio, 0, mDy, mShadowColor);
            valuePaint.setColor(Color.parseColor("#f4f4f4"));
        }

        if (centerDrawable == null) {
            centerDrawable = (Drawable) getResources().getDrawable(
                    R.drawable.common_gray_bg);
        }
    }

    /**
     * 获取所需的高度布局
     *
     * @param layout 布局
     * @return 布局的高度
     */
    private int getDesiredHeight(Layout layout) {
        if (layout == null) {
            return 0;
        }

        int desired = getItemHeight() * visibleItems - itemOffset * two
                - ADDITIONAL_ITEM_HEIGHT;

        // 最底高度
        desired = Math.max(desired, getSuggestedMinimumHeight());

        return desired;
    }

    /**
     * 返回指定索引处的值
     *
     * @param index 索引
     * @return 指定索引的值
     */
    private String getTextItem(int index) {
        if (mAdapter == null || mAdapter.getItemsCount() == 0) {
            return null;
        }
        int count = mAdapter.getItemsCount();
        if ((index < 0 || index >= count) && !mIsCyclic) {
            return null;
        } else {
            while (index < 0) {
                index = count + index;
            }
        }

        index %= count;
        return mAdapter.getItem(index);
    }

    /**
     * 创建值文本
     *
     * @param useCurrentValue
     * @return the text
     */
    private String buildText(boolean useCurrentValue) {
        StringBuilder itemsText = new StringBuilder();
        int addItems = visibleItems / two + 1;

        for (int i = currentItem - addItems; i <= currentItem + addItems; i++) {
            if (useCurrentValue || i != currentItem) {
                String text = getTextItem(i);
                if (text != null) {
                    if (text.length() > maxTextLength) {
                        text = text.substring(0, maxTextLength);
                    }
                    itemsText.append(text);
                }
            }
            if (i < currentItem + addItems) {
                itemsText.append("\n");
            }
        }

        return itemsText.toString();
    }

    /**
     * 获取的最大项的长度，可以存在
     *
     * @return 最大项的长度
     */
    private int getMaxTextLength() {
        WheelAdapter adapter = getAdapter();
        if (adapter == null) {
            return 0;
        }

        int adapterLength = adapter.getMaximumLength();
        maxTextLength = adapterLength;
        if (adapterLength > 0) {
            return adapterLength;
        }

        String maxText = null;
        int addItems = visibleItems / two;
        for (int i = Math.max(currentItem - addItems, 0); i < Math.min(
                currentItem + visibleItems, adapter.getItemsCount()); i++) {
            String text = adapter.getItem(i);
            if (text != null
                    && (maxText == null || maxText.length() < text.length())) {
                maxText = text;
            }
        }

        return maxText != null ? maxText.length() : 0;
    }

    /**
     * 获取滚轮的高度
     *
     * @return 滚轮的高度
     */
    private int getItemHeight() {
        if (mItemHeight != 0) {
            return mItemHeight;
        } else if (itemsLayout != null && itemsLayout.getLineCount() > two) {
            mItemHeight = itemsLayout.getLineTop(two)
                    - itemsLayout.getLineTop(1);
            return mItemHeight;
        }

        return getHeight() / visibleItems;
    }

    /**
     * 计算控制宽度，并创建文本布局
     *
     * @param widthSize 布局高度
     * @param mode      布局模式
     * @return 控制的高度
     */
    private int calculateLayoutWidth(int widthSize, int mode) {
        initResourcesIfNecessary();

        int width = widthSize;

        int maxLength = getMaxTextLength();
        if (maxLength > 0) {
            float textWidth = (float) Math.ceil(Layout.getDesiredWidth(PROVINCE,
                    itemsPaint));
            itemsWidth = (int) (maxLength * textWidth);
        } else {
            itemsWidth = 0;
        }
        itemsWidth += ADDITIONAL_ITEMS_SPACE; // make it some more

        labelWidth = 0;
        if (label != null && label.length() > 0) {
            labelWidth = (int) Math.ceil(Layout.getDesiredWidth(label,
                    valuePaint));
        }

        boolean recalculate = false;
        if (mode == MeasureSpec.EXACTLY) {
            width = widthSize;
            recalculate = true;
        } else {
            width = itemsWidth + labelWidth + two * PADDING;
            if (labelWidth > 0) {
                width += LABEL_OFFSET;
            }

            width = Math.max(width, getSuggestedMinimumWidth());

            if (mode == MeasureSpec.AT_MOST && widthSize < width) {
                width = widthSize;
                recalculate = true;
            }
        }

        if (recalculate) {
            // recalculate width
            int pureWidth = width - LABEL_OFFSET - two * PADDING;
            if (pureWidth <= 0) {
                itemsWidth = labelWidth = 0;
            }
            if (labelWidth > 0) {
                double newWidthItems = (double) itemsWidth * pureWidth
                        / (itemsWidth + labelWidth);

                if (isPad) {
                    itemsWidth = (int) newWidthItems - 95;
                } else {
                    itemsWidth = (int) newWidthItems - 50;
                }
                labelWidth = pureWidth - itemsWidth;
            } else {
                itemsWidth = pureWidth + LABEL_OFFSET; // no label
            }
        }

        if (itemsWidth > 0) {
            createLayouts(itemsWidth, labelWidth);
        }

        return width;
    }

    /**
     * 创建布局
     *
     * @param widthItems 布局的宽度
     * @param widthLabel 标签布局的宽度
     */
    private void createLayouts(int widthItems, int widthLabel) {
        if (itemsLayout == null || itemsLayout.getWidth() > widthItems) {
            itemsLayout = new StaticLayout(buildText(isScrollingPerformed),
                    itemsPaint, widthItems,
                    widthLabel > 0 ? Layout.Alignment.ALIGN_OPPOSITE
                            : Layout.Alignment.ALIGN_CENTER, 1,
                    ADDITIONAL_ITEM_HEIGHT, false);
        } else {
            itemsLayout.increaseWidthTo(widthItems);
        }

        if (!isScrollingPerformed
                && (valueLayout == null || valueLayout.getWidth() > widthItems)) {
            String text = getAdapter() != null ? getAdapter().getItem(
                    currentItem) : null;
            valueLayout = new StaticLayout(text != null ? text : "",
                    valuePaint, widthItems,
                    widthLabel > 0 ? Layout.Alignment.ALIGN_OPPOSITE
                            : Layout.Alignment.ALIGN_CENTER, 1,
                    ADDITIONAL_ITEM_HEIGHT, false);
        } else if (isScrollingPerformed) {
            valueLayout = null;
        } else {
            valueLayout.increaseWidthTo(widthItems);
        }

        if (widthLabel > 0) {
            if (labelLayout == null || labelLayout.getWidth() > widthLabel) {
                labelLayout = new StaticLayout(label, valuePaint, widthLabel,
                        Layout.Alignment.ALIGN_NORMAL, 1,
                        ADDITIONAL_ITEM_HEIGHT, false);
            } else {
                labelLayout.increaseWidthTo(widthLabel);
            }
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        int width = calculateLayoutWidth(widthSize, widthMode);

        int height;
        if (heightMode == MeasureSpec.EXACTLY) {
            height = heightSize;
        } else {
            height = getDesiredHeight(itemsLayout);

            if (heightMode == MeasureSpec.AT_MOST) {
                height = Math.min(height, heightSize);
            }
        }

        setMeasuredDimension(width, height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (itemsLayout == null) {
            if (itemsWidth <= 0) {
                calculateLayoutWidth(getWidth(), MeasureSpec.EXACTLY);
            } else {
                createLayouts(itemsWidth, labelWidth);
            }
        }

        drawCenterRect(canvas);
        if (itemsWidth > 0) {
            canvas.save();
            canvas.translate(PADDING, -itemOffset);
            drawItems(canvas);
            drawValue(canvas);
            canvas.restore();
        }
    }

    /**
     * 绘制值和标签布局
     *
     * @param canvas 画布
     */
    private void drawValue(Canvas canvas) {
        valuePaint.setColor(VALUE_TEXT_COLOR);
        valuePaint.drawableState = getDrawableState();

        Rect bounds = new Rect();
        itemsLayout.getLineBounds(visibleItems / two, bounds);

        // draw label
        if (labelLayout != null) {
            canvas.save();
            canvas.translate(itemsLayout.getWidth() + LABEL_OFFSET, bounds.top);
            labelLayout.draw(canvas);
            canvas.restore();
        }

        if (valueLayout != null) {
            canvas.save();
            canvas.translate(0, bounds.top + scrollingOffset);
            valueLayout.draw(canvas);
            canvas.restore();
        }
    }

    /**
     * 绘制选项
     *
     * @param canvas 画布
     */
    private void drawItems(Canvas canvas) {
        canvas.save();
        int top = itemsLayout.getLineTop(1);
        canvas.translate(0, -top + scrollingOffset);
        itemsPaint.setColor(ITEMS_TEXT_COLOR);
        itemsPaint.drawableState = getDrawableState();
        itemsLayout.draw(canvas);
        canvas.restore();
    }

    /**
     * 绘制矩形
     *
     * @param canvas 画布
     */
    private void drawCenterRect(Canvas canvas) {
        int center = getHeight() / two;
        int offset = getItemHeight() / two;
        centerDrawable.setBounds(0, center - offset, getWidth(), center
                + offset);
        centerDrawable.draw(canvas);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        WheelAdapter adapter = getAdapter();
        if (adapter == null) {
            return true;
        }

        if (!gestureDetector.onTouchEvent(event)
                && event.getAction() == MotionEvent.ACTION_UP) {
            justify();
        }
        return true;
    }

    /**
     * 滚动轮
     *
     * @param delta 滚动值
     */
    private void doScroll(int delta) {
        scrollingOffset += delta;

        int count = scrollingOffset / getItemHeight();
        int pos = currentItem - count;
        if (mIsCyclic && mAdapter.getItemsCount() > 0) {
            // fix position by rotating
            while (pos < 0) {
                pos += mAdapter.getItemsCount();
            }
            pos %= mAdapter.getItemsCount();
        } else if (isScrollingPerformed) {
            //
            if (pos < 0) {
                count = currentItem;
                pos = 0;
            } else if (pos >= mAdapter.getItemsCount()) {
                count = currentItem - mAdapter.getItemsCount() + 1;
                pos = mAdapter.getItemsCount() - 1;
            }
        } else {
            // fix position
            pos = Math.max(pos, 0);
            pos = Math.min(pos, mAdapter.getItemsCount() - 1);
        }

        int offset = scrollingOffset;
        if (pos != currentItem) {
            setCurrentItem(pos, false);
        } else {
            invalidate();
        }

        // update offset
        scrollingOffset = offset - count * getItemHeight();
        if (scrollingOffset > getHeight()) {
            scrollingOffset = scrollingOffset % getHeight() + getHeight();
        }
    }

    /**
     * 下一个消息队列。清除队列前。
     *
     * @param message 设置消息
     */
    private void setNextMessage(int message) {
        clearMessages();
        animationHandler.sendEmptyMessage(message);
    }

    /**
     * 清除的消息队列
     */
    private void clearMessages() {
        animationHandler.removeMessages(messageScroll);
        animationHandler.removeMessages(messageJustify);
    }

    /**
     * Justifies wheel
     */
    private void justify() {
        if (mAdapter == null) {
            return;
        }

        lastScrollY = 0;
        int offset = scrollingOffset;
        int itemHeight = getItemHeight();
        boolean needToIncrease = offset > 0 ? currentItem < mAdapter
                .getItemsCount() : currentItem > 0;
        if ((mIsCyclic || needToIncrease)
                && Math.abs((float) offset) > (float) itemHeight / two) {
            if (offset < 0) {
                offset += itemHeight + MIN_DELTA_FOR_SCROLLING;
            } else {
                offset -= itemHeight + MIN_DELTA_FOR_SCROLLING;
            }
        }
        if (Math.abs(offset) > MIN_DELTA_FOR_SCROLLING) {
            scroller.startScroll(0, 0, 0, offset, SCROLLING_DURATION);
            setNextMessage(messageJustify);
        } else {
            finishScrolling();
        }
    }

    /**
     * 开始滚动
     */
    private void startScrolling() {
        if (!isScrollingPerformed) {
            isScrollingPerformed = true;
            notifyScrollingListenersAboutStart();
        }
    }

    /**
     * 完成滚动
     */
    void finishScrolling() {
        if (isScrollingPerformed) {
            notifyScrollingListenersAboutEnd();
            isScrollingPerformed = false;
        }
        invalidateLayouts();
        invalidate();
    }

    /**
     * 滚动的效果
     *
     * @param itemsToScroll 选项滚动
     * @param time          滚动时间
     */
    public void scroll(int itemsToScroll, int time) {
        scroller.forceFinished(true);

        lastScrollY = scrollingOffset;
        int offset = itemsToScroll * getItemHeight();

        scroller.startScroll(0, lastScrollY, 0, offset - lastScrollY, time);
        setNextMessage(messageScroll);

        startScrolling();
    }

    /**
     * @param context
     * @return
     */
    public static boolean isPad(Context context) {
        return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE;
    }
}
